package impl

import (
	"context"
	"fmt"

	"gitee.com/go-course/go8/projects/devcloud/mcenter/apps/token"
	"github.com/infraboard/mcube/exception"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

func (s *service) save(ctx context.Context, tk *token.Token) error {
	if _, err := s.col.InsertOne(ctx, tk); err != nil {
		return exception.NewInternalServerError("inserted token(%s) document error, %s",
			tk.AccessToken, err)
	}

	return nil
}

func (s *service) get(ctx context.Context, id string) (*token.Token, error) {
	filter := bson.M{"_id": id}

	ins := token.NewToken(token.NewIssueTokenRequest())
	if err := s.col.FindOne(ctx, filter).Decode(ins); err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, exception.NewNotFound("token %s not found", id)
		}

		return nil, exception.NewInternalServerError("find token %s error, %s", id, err)
	}

	return ins, nil
}

func (s *service) update(ctx context.Context, tk *token.Token) error {
	if _, err := s.col.UpdateByID(ctx, tk.AccessToken, bson.M{"$set": tk}); err != nil {
		if err == mongo.ErrNoDocuments {
			return exception.NewNotFound("token %s not found", tk.AccessToken)
		}

		return exception.NewInternalServerError("find token %s error, %s", tk.AccessToken, err)
	}

	return nil
}

func (s *service) delete(ctx context.Context, ins *token.Token) error {
	if ins == nil || ins.AccessToken == "" {
		return fmt.Errorf("access tpken is nil")
	}

	result, err := s.col.DeleteOne(ctx, bson.M{"_id": ins.AccessToken})
	if err != nil {
		return exception.NewInternalServerError("delete token(%s) error, %s", ins.AccessToken, err)
	}

	if result.DeletedCount == 0 {
		return exception.NewNotFound("book %s not found", ins.AccessToken)
	}

	return nil
}

func newQueryRequest(r *token.QueryTokenRequest) *queryRequest {
	return &queryRequest{
		r,
	}
}

// 构建mongodb查询参数
type queryRequest struct {
	*token.QueryTokenRequest
}

// 分页
func (r *queryRequest) FindOptions() *options.FindOptions {
	pageSize := int64(r.Page.PageSize)
	skip := int64(r.Page.PageSize) * int64(r.Page.PageNumber-1)

	opt := &options.FindOptions{
		// DESC -1
		Sort: bson.D{
			{Key: "issue_at", Value: -1},
		},
		// LIMIT offset,limit
		Limit: &pageSize,
		Skip:  &skip,
	}

	return opt
}

// 过滤条件
func (r *queryRequest) FindFilter() bson.M {
	filter := bson.M{}

	if r.Domain != "" {
		filter["domain"] = r.Domain
	}
	if r.UserId != "" {
		filter["user_id"] = r.UserId
	}
	if r.Platform != nil {
		filter["platform"] = r.Platform
	}
	if r.IsBlock != nil {
		filter["status.is_block"] = r.IsBlock
	}
	if r.Username != "" {
		filter["username"] = r.Username
	}

	return filter
}
